package com.ruoyi.common.utils;

import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

/**
 * 缓存支持工具
 *
 * @author herman
 * @description:
 * @date 2023-08-10 14:23:29
 * @version: 1.0
 */
@Component
public class CacheSupportUtils {

    /**
     * 本地缓存查询
     *
     * @param id              缓存id
     * @param cache           缓存容器
     * @param dbQuery         查询数据库方法
     * @param resultExtractor 结果转换方法
     */
    public static <K, V, PO> V getFromCacheOrDB(K id,
                                                Map<K, V> cache,
                                                Function<K, PO> dbQuery,
                                                Function<PO, V> resultExtractor,
                                                boolean cacheNull) {
        if (id == null) return null;
        return Optional.ofNullable(cache.get(id))
                .or(() -> {
                    PO po = dbQuery.apply(id);
                    if (po == null) return Optional.empty();
                    V result = resultExtractor.apply(po);

                    if (result != null || cacheNull) {
                        cache.put(id, result);
                    }
                    return Optional.ofNullable(result);
                })
                .orElse(null);
    }

    /**
     * 缓存加载器
     *
     * @param loader 数据加载方法
     * @param cache  缓存
     * @param <K>    缓存key
     * @param <V>    缓存value
     * @return Function，如果没有则使用数据加载方法加载
     */
    public static <K, V> Function<K, V> cachedLoader(Function<K, V> loader, Map<K, V> cache) {
        return key -> cache.computeIfAbsent(key, loader);
    }
}
